// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) braces deadcode 

package anyVehicle;


import java.util.ArrayList;
import java.util.List;

import net.minecraft.src.AxisAlignedBB;
import net.minecraft.src.Block;
import net.minecraft.src.DamageSource;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.Material;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.TileEntity;
import net.minecraft.src.Vec3D;
import net.minecraft.src.World;
import net.minecraft.src.mod_AnyVehicle;

import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;

import com.bulletphysics.dynamics.RigidBody;

// Referenced classes of package net.minecraft.src:
//            Entity, World, Block, Item, 
//            AxisAlignedBB, Material, MathHelper, EntityPlayer, 
//            DamageSource, NBTTagCompound

/**
 * @author As You Wish
 * 
 */
public class Vehicle extends Entity {
	private boolean isDying = false;
	private double flotationLine;

	public double hitPoints;
	public double timeSinceHit;

	protected double maxCollisionSpeed = 0.14999999999999999D; // TODO Calculate
	public float damageTaken;
	
	protected int widthBlocks;
	protected int heightBlocks;
	protected int lengthBlocks;
	public VehicleBlocks vehicleBlocks;
	private float nextStepDistance;

	public float forwardDirection = 1;
	
	private EntityRigidBody body;
	

	public void setBody(EntityRigidBody body) {
		this.body = body;
	}

	public EntityRigidBody getBody() {
		return body;
	}

	public Vehicle(World world) {
		super(world);
		vehicleBlocks = new VehicleBlocks(world, this);
		nextStepDistance = 1;
		
	}

	public Vehicle(World world, double x, double y, double z) {
		this(world);
		setPosition(x, y + (double) yOffset, z);
		motionX = 0.0D;
		motionY = 0.0D;
		motionZ = 0.0D;
		prevPosX = x;
		prevPosY = y;
		prevPosZ = z;
		rotationPitch=0;
		rotationYaw=0;
	}

	public Vehicle(World world, float x, float y, float z, int xCreator, int yCreator, int zCreator, double flotationLine) {
		this(world, x, y, z);
		copyBlueprintFrom(xCreator, yCreator, zCreator);
		hitPoints = getMaxHitPoints();
		setPosition(x, y + (double) yOffset, z);
		this.flotationLine = flotationLine;
//		worldObj.sim.getBodyManager().updateRigidBodyFromEntity(body, this);
		body = worldObj.sim.getBodyManager().getVehicleBodyFromEntity(this);
	}



	private void copyBlueprintFrom(int x, int y, int z) {
		Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
		
		if (block instanceof BlockVehicleCreator) {
			BlockVehicleCreator creator = (BlockVehicleCreator) block;
			TileEntityScaffold scaffoldTE = (TileEntityScaffold) worldObj.getBlockTileEntity(x, y, z);

			// TODO Determine size automatically
			int l = scaffoldTE.getLengthBlocks() - 2;
			int h = scaffoldTE.getHeightBlocks() - 2;
			int w = scaffoldTE.getWidthBlocks() - 2;
			setSizeBlocks(l, h, w);
			Vec3D corner = getLowerBackLeftCorner();

			copyBlocks(worldObj, x + 1, y + 1, z + 1, l, h, w, vehicleBlocks, (int) corner.xCoord, (int) corner.yCoord, (int) corner.zCoord);
			
		}
	}

	public void onUpdate() {
		super.onUpdate();

		prevPosX = posX;
		prevPosY = posY;
		prevPosZ = posZ;

		if (timeSinceHit > 0) {
			timeSinceHit--;
		}
		if (damageTaken > 0) {
			damageTaken--;
		}
		if (worldObj.multiplayerWorld) {
			updatePositionMultiplayer();
			return;
		}

		if (isDying) {
			sink();

		} else {
			onWaterMotionUpdate();
//			transmitMotionFromMountedUnit();
//			capMaxSpeedInPlaneXZ();
			onGroundMotionUpdate();
//			moveEntity(motionX, motionY, motionZ);
//			double magnitudeMotionXZPlane = Math.sqrt(motionX * motionX + motionZ * motionZ);
			double magnitudeMotionXZPlane = body.getLinearVelocity(new javax.vecmath.Vector3f()).length();
			splashWater(magnitudeMotionXZPlane);
			handleCollisionDamage(magnitudeMotionXZPlane);
			handleFireDamage();
//			applyFriction();

//			updatePitch();
//			updateYaw();
//			setRotation(rotationYaw, rotationPitch);

			handleCollisionsWithEntities();

//			handleSnowMovement();

//			if (riddenByEntity != null && riddenByEntity.isDead) {
//				riddenByEntity = null;
//			}
			handleDestruction();

//			vehicleBlocks.updateEntities();
			vehicleBlocks.tick();
			vehicleBlocks.randomDisplayUpdates(0, 0, 0);

		}
	}

	public void onGroundMotionUpdate() {
		if (onGround) {
			body.setDamping(0.1f, 0.2f);
		} else {
			body.setDamping(0.5f, 0.5f);
		}
	}

	private void onWaterMotionUpdate() {
		double fractionOfShipUnderWater = getFractionOfShipUnderWater();
		body.applyCentralForce(new javax.vecmath.Vector3f(0f, 10f +10f * (float)  (widthBlocks * heightBlocks * fractionOfShipUnderWater * heightBlocks), 0f));
//		body.applyForce(new javax.vecmath.Vector3f(0f, 50f * (float)  (widthBlocks * heightBlocks * fractionOfShipUnderWater * heightBlocks), 0f), new javax.vecmath.Vector3f(-0.5f, 0f, 0f));
	}

	private void sink() {
		motionX *= 0.9D;
		motionY = -0.07D;
		motionZ *= 0.9D;
		moveEntity(motionX, motionY, motionZ);
		if (isCollidedVertically) {
			destroyShip();
		}
	}

	private final void handleFireDamage() {
		if (isBurning()) {
			hitPoints -= 0.5D;
		}

	}

	private final void handleDestruction() {
		if (hitPoints < 0D) {
			isDying = true;
		}
	}

	private final void handleSnowMovement() {
		for (int k1 = 0; k1 < 4; k1++) {
			int l1 = MathHelper.floor_double(posX + ((double) (k1 % 2) - 0.5D) * 0.80000000000000004D);
			int i2 = MathHelper.floor_double(posY);
			int j2 = MathHelper.floor_double(posZ + ((double) (k1 / 2) - 0.5D) * 0.80000000000000004D);
			if (worldObj.getBlockId(l1, i2, j2) == Block.snow.blockID) {
				worldObj.setBlockWithNotify(l1, i2, j2, 0);
			}
		}
	}

	private final void updatePitch() {
		rotationPitch = 0.0F;
	}

	private final void updateYaw() {
		double newYaw = rotationYaw;
		double dx = prevPosX - posX;
		double dz = prevPosZ - posZ;
		if (dx * dx + dz * dz > 0.001D) {
			newYaw = (float) ((Math.atan2(dz, dx) * 180D) / 3.1415926535897931D);
		}

		rotationYaw += calculate_dYaw(newYaw);
	}

	/**
	 * Handles potentially fatal collisions with other elements in the world
	 * 
	 * @param speed
	 */
	private final void handleCollisionDamage(double speed) {

		if (isCollidedHorizontally && speed > maxCollisionSpeed) {
			if (!worldObj.multiplayerWorld) {
				hitPoints -= speed * (Math.random() * 10D + 10);
				worldObj.playSoundAtEntity(this, "mob.ghast.fireball", 0.5F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);

			}
		}
	}

	private final double calculate_dYaw(double newYaw) {
		double dYaw;
		for (dYaw = newYaw - (double) rotationYaw; dYaw >= 180D; dYaw -= 360D) {
		}
		for (; dYaw < -180D; dYaw += 360D) {
		}
		if (dYaw > 20D) {
			dYaw = 20D;
		}
		if (dYaw < -20D) {
			dYaw = -20D;
		}
		return dYaw;
	}

	private final void applyFriction() {
		motionX *= 0.995D;
		motionY *= 0.96D;
		motionZ *= 0.995D;
	}

	private final void destroyShip() {
		setEntityDead();
		// for (int i = 0; i < shipBlockData.length; i++) {
		// if (shipBlockData[i] != 0) {
		// dropItemWithOffset(shipBlockData[i], 1, 0.0F);
		// }
		// }
		createWreck();
		worldObj.playSoundAtEntity(this, "mob.ghast.fireball", 0.5F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
	}

	private void createWreck() {
		Vec3D corner = getLowerBackLeftCorner();
		int x = (int) (posX + corner.xCoord);
		int y = (int) (posY + corner.yCoord);
		int z = (int) (posZ - corner.zCoord);

		copyBlocks(vehicleBlocks, (int) corner.xCoord, (int) corner.yCoord, (int) corner.zCoord, lengthBlocks, heightBlocks, widthBlocks, worldObj, x, y, z);
		// for (int i = 1; i < lengthBlocks; i++) {
		// for (int j = 1; j < heightBlocks; j++) {
		// for (int k = 1; k < widthBlocks; k++) {
		// int blockID = vehicleBlocks.getBlockId(i, j, k);
		// if (blockID != 0) {
		// worldObj.setBlockAndMetadataWithNotify(x + i, y + j, z + k, blockID,
		// vehicleBlocks.getBlockMetadata(i, j, k));
		// }
		// }
		// }
		// }

	}

	private final void splashWater(double magnitudeMotionXZPlane) {
		if (magnitudeMotionXZPlane > 5D) {
			double xYaw = Math.cos(((double) rotationYaw * 3.1415926535897931D) / 180D);
			double zYaw = Math.sin(((double) rotationYaw * 3.1415926535897931D) / 180D);
			for (int i1 = 0; (double) i1 < 1.0D + magnitudeMotionXZPlane * 60D; i1++) {
				double randomSplashDelta1 = rand.nextFloat() * 2.0F - 1.0F;
				double randomSplashDelta2 = (double) (rand.nextInt(2) * 2 - 1) * 0.69999999999999996D;
				if (rand.nextBoolean()) {
					double xSplash = (posX - xYaw * randomSplashDelta1 * 0.80000000000000004D) + zYaw * randomSplashDelta2;
					double zSplash = posZ - zYaw * randomSplashDelta1 * 0.80000000000000004D - xYaw * randomSplashDelta2;
					worldObj.spawnParticle("splash", xSplash, posY - 0.125D, zSplash, motionX, motionY, motionZ);
				} else {
					double xSplash = posX + xYaw + zYaw * randomSplashDelta1 * 0.69999999999999996D;
					double zSplash = (posZ + zYaw) - xYaw * randomSplashDelta1 * 0.69999999999999996D;
					worldObj.spawnParticle("splash", xSplash, posY - 0.125D, zSplash, motionX, motionY, motionZ);
				}
			}

		}
	}


	private final void capMaxSpeedInPlaneXZ() {
		double maxMotionInXZPlane = 0.40000000000000002D;
		if (motionX < -maxMotionInXZPlane) {
			motionX = -maxMotionInXZPlane;
		}
		if (motionX > maxMotionInXZPlane) {
			motionX = maxMotionInXZPlane;
		}
		if (motionZ < -maxMotionInXZPlane) {
			motionZ = -maxMotionInXZPlane;
		}
		if (motionZ > maxMotionInXZPlane) {
			motionZ = maxMotionInXZPlane;
		}
	}

	private final void transmitMotionFromMountedUnit() {
		if (riddenByEntity != null) {
			motionX += riddenByEntity.motionX * 0.20000000000000001D;
			motionZ += riddenByEntity.motionZ * 0.20000000000000001D;
		}
	}

	private final void updatePositionMultiplayer() {
		// FIXME Add support for multiplayer
		// if(boatPosRotationIncrements > 0)
		// {
		// double d1 = posX + (boatX - posX) /
		// (double)boatPosRotationIncrements;
		// double d6 = posY + (boatY - posY) /
		// (double)boatPosRotationIncrements;
		// double d10 = posZ + (boatZ - posZ) /
		// (double)boatPosRotationIncrements;
		// double d14;
		// for(d14 = boatYaw - (double)rotationYaw; d14 < -180D; d14 += 360D) {
		// }
		// for(; d14 >= 180D; d14 -= 360D) { }
		// rotationYaw += d14 / (double)boatPosRotationIncrements;
		// rotationPitch += (boatPitch - (double)rotationPitch) /
		// (double)boatPosRotationIncrements;
		// boatPosRotationIncrements--;
		// setPosition(d1, d6, d10);
		// setRotation(rotationYaw, rotationPitch);
		// } else
		// {
		double newPosX = posX + motionX;
		double newPosY = posY + motionY;
		double newPosZ = posZ + motionZ;
		setPosition(newPosX, newPosY, newPosZ);
		onGroundMotionUpdate();
		applyFriction();
	}

	private final void onWaterMotionUpdateOld() {
		double fractionOfShipUnderWater = getFractionOfShipUnderWater();
		if (fractionOfShipUnderWater < 1.0D) // If the boat is not totally
												// submerged
		{
			double buoyancyPushStrength = fractionOfShipUnderWater - flotationLine; 
			motionY += 2D * 0.039999999105930328D * buoyancyPushStrength;
		} else {
			if (motionY < 0.0D) {
				motionY /= 2D;
			}
			motionY += 0.0070000002160668373D;
		}
	}

	public double getFractionOfShipUnderWater() {
		int totalSubdivisions = 6;
		double fractionOfShipUnderWater = 0.0D;
		for (int subdivision_i = 0; subdivision_i < totalSubdivisions; subdivision_i++) {
			double minYSubdivision = (boundingBox.minY + ((boundingBox.maxY - boundingBox.minY) * (double) (subdivision_i + 0)) / (double) totalSubdivisions) + 0.5D;
			double maxYSubdivision = (boundingBox.minY + ((boundingBox.maxY - boundingBox.minY) * (double) (subdivision_i + 1)) / (double) totalSubdivisions) + 0.5D;
			AxisAlignedBB subdivisionBB = AxisAlignedBB.getBoundingBoxFromPool(boundingBox.minX, minYSubdivision, boundingBox.minZ, boundingBox.maxX,
					maxYSubdivision, boundingBox.maxZ);
			if (worldObj.isAABBInMaterial(subdivisionBB, Material.water)) {
				fractionOfShipUnderWater += 1.0D / (double) totalSubdivisions;
			}
		}
		return fractionOfShipUnderWater;
	}

	public boolean interact(EntityPlayer entityplayer) {
		if (riddenByEntity != null && (riddenByEntity instanceof EntityPlayer) && riddenByEntity != entityplayer) {
			return true;
		} else if (!worldObj.multiplayerWorld) {
			entityplayer.mountEntity(this);
		}
//		System.out.println(boundingBox.minX + " " + boundingBox.minY + " " + boundingBox.minZ + " " + boundingBox.maxX + " " + boundingBox.maxY + " "
//				+ boundingBox.maxZ);
		return true;
	}

	@Override
	public boolean attackEntityFrom(DamageSource damagesource, int i) {
		if (worldObj.multiplayerWorld || isDead) {
			return true;
		}
		forwardDirection = -forwardDirection;
		timeSinceHit = 10;
		damageTaken += i * 10;
		hitPoints -= 10 * i;
//		System.out.println(hitPoints);
		setBeenAttacked();
		return true;

	}

	public void updateRiderPosition() {
		if (riddenByEntity == null) {
			return;
		} else {
			// double rider_dx = Math.cos(((double) rotationYaw *
			// 3.1415926535897931D) / 180D) * 0.40000000000000002D;
			// double rider_dz = Math.sin(((double) rotationYaw *
			// 3.1415926535897931D) / 180D) * 0.40000000000000002D;
			// riddenByEntity.setPosition(posX + rider_dx, posY +
			// getMountedYOffset() + riddenByEntity.getYOffset(), posZ +
			// rider_dz);
			Vector4f localPos = new Vector4f(0F, heightBlocks, 0F, 1);
			Vector4f absPos = VehicleUtil.localPosToParent(localPos, getPosVector3f(), getRotVector3f());
			riddenByEntity.setPosition(absPos.x, absPos.y, absPos.z);
			return;
		}
	}


	@Override
	protected void entityInit() {

	}

	public void setSizeBlocks(int l, int h, int w) {
		lengthBlocks = l;
		height = heightBlocks = h;
		width = widthBlocks = w;

		updateBoundingBox();
	}

	@Override
	public void setPosition(double d, double d1, double d2) {
		posX = d;
		posY = d1;
		posZ = d2;
		updateBoundingBox();
	}

	public void updateBoundingBox() {
		// boundingBox.setBounds(posX - lengthBlocks / 2F, posY /*- heightBlocks
		// / 2F */+ yOffset + ySize - 1, posZ - widthBlocks / 2F,
		// posX + lengthBlocks / 2F, posY + yOffset + ySize - 1 + heightBlocks,
		// posZ + widthBlocks / 2F);
		Vec3D c = getLowerBackLeftCorner();
		Vec3D c2 = getUpperFrontRightCorner(c);
		boundingBox.setBounds(posX + c.xCoord, posY + c.yCoord, posZ + c.zCoord, posX + c2.xCoord, posY + c2.yCoord, posZ + c2.zCoord);
	}

	@Override
	protected void readEntityFromNBT(NBTTagCompound nbttagcompound) {
		flotationLine = nbttagcompound.getDouble("flotationLine");
		if (flotationLine < 0D) {
			flotationLine = 0.2D;
		}
		hitPoints = nbttagcompound.getDouble("hitPoints");
		setSizeBlocks(nbttagcompound.getInteger("lengthBlocks"), nbttagcompound.getInteger("heightBlocks"), nbttagcompound.getInteger("widthBlocks"));
//		setPosition(posX, posY, posZ);
		vehicleBlocks = new VehicleBlocks(worldObj, this, nbttagcompound.getString("vehicleID"));
		body = worldObj.sim.getBodyManager().getVehicleBodyFromEntity(this);
//		System.out.printf("Pos: %.2f, %.2f, %.2f\n", posX, posY, posZ);

	}
	@Override
	protected void writeEntityToNBT(NBTTagCompound nbttagcompound) {
		nbttagcompound.setDouble("flotationLine", flotationLine);
		nbttagcompound.setDouble("hitPoints", hitPoints);
		// FIXME Vehicle moves north-west each time is saved
//		nbttagcompound.setTag("Pos", newDoubleNBTList(new double[] { posX, posY, posZ }));
		nbttagcompound.setInteger("lengthBlocks", lengthBlocks);
		nbttagcompound.setInteger("heightBlocks", heightBlocks);
		nbttagcompound.setInteger("widthBlocks", widthBlocks);
		nbttagcompound.setString("vehicleID", vehicleBlocks.getVehicleID());
		vehicleBlocks.saveWorld(true, null);
	}

	public int getWidthBlocks() {
		return widthBlocks;
	}

	public void setWidthBlocks(int widthBlocks) {
		this.widthBlocks = widthBlocks;
	}

	public int getHeightBlocks() {
		return heightBlocks;
	}

	public void setHeightBlocks(int heightBlocks) {
		this.heightBlocks = heightBlocks;
	}

	public int getLengthBlocks() {
		return lengthBlocks;
	}

	public void setLengthBlocks(int lengthBlocks) {
		this.lengthBlocks = lengthBlocks;
	}

	public Vector4f parentPosToLocal(Vector4f parentPos) {
		parentPos.x -= motionX;
		parentPos.y -= motionY;
		parentPos.z -= motionZ;
		return VehicleUtil.parentPosToLocal(parentPos, getPosVector3f(), getRotVector3f());
	}

	public Vector4f localPosToParent(Vector4f localPos) {
		Vector4f parentPos = VehicleUtil.localPosToParent(localPos, getPosVector3f(), getRotVector3f());
		parentPos.x += motionX;
		parentPos.y += motionY;
		parentPos.z += motionZ;
		return parentPos;
		
	}

	public Vector3f getPosVector3f() {
		return VehicleUtil.getPosVector3f(this);
	}
	
	public Vector3f getLastTickPos3f() {
		return VehicleUtil.getLastTickPosVector3f(this);
	}

	public Vector4f getLastTickPos4f() {
		return VehicleUtil.getLastTickPosVector4f(this);
	}

	
	public Vector4f getPosVector4f() {
		return VehicleUtil.getPosVector4f(this);
	}

	public Vector3f getRotVector3f() {
		return VehicleUtil.getRotVector3f(this);
	}

	@Override
	public void onCollideWithPlayer(EntityPlayer entityplayer) {
		// System.out.println("Collided with player");
	}

	public Vec3D getUpperFrontRightCorner(Vec3D lowerBackLeftCorner) {
		return lowerBackLeftCorner.addVector(lengthBlocks, heightBlocks, widthBlocks);
	}

	public Vec3D getLowerBackLeftCorner() {
		return Vec3D.createVector(-lengthBlocks / 2, yOffset - ySize, -widthBlocks / 2);
	}

	public double getMaxHitPoints() {
		return Math.sqrt(lengthBlocks * heightBlocks * lengthBlocks);
	}

	public void copyBlocks(World world1, int x, int y, int z, int l, int h, int w, World world2, int x2, int y2, int z2) {
		int i2 = x2;
		for (int i = x; i < x + l; i++) {
			int j2 = y2;
			for (int j = y; j < y + h; j++) {
				int k2 = z2;
				for (int k = z; k < z + w; k++) {
					int blockID = world1.getBlockId(i, j, k);
					int blockMD = world1.getBlockMetadata(i, j, k);
					if (blockID != 0 && blockID != 8 && blockID != 9 && blockID != mod_AnyVehicle.BLOCK_ID_VEHICLE_CREATOR) {
						world2.setBlockAndMetadataWithNotify(i2, j2, k2, blockID, blockMD);

						TileEntity tileEntity = world1.getBlockTileEntity(i, j, k);
						if (tileEntity != null) {
							world1.setBlockAndMetadata(i, j, k, 0, 0);
							tileEntity.validate();
							world2.setBlockTileEntity(i2, j2, k2, tileEntity);
						}

					}
					k2++;

				}
				j2++;
			}
			i2++;
		}

	}






//	public AxisAlignedBB getLocalBB(AxisAlignedBB bb) {
//		Vector4f minPos = VehicleUtil.parentPosToLocal(new Vector4f((float)bb.minX, (float)bb.minY, (float)bb.minZ, 1F), getPosVector3f(), getRotVector3f());
//		Vector4f maxPos = VehicleUtil.parentPosToLocal(new Vector4f((float)bb.maxX, (float)bb.maxY, (float)bb.maxZ, 1F), getPosVector3f(), getRotVector3f());
//		return AxisAlignedBB.getBoundingBox(minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z);
//	}


	protected final void handleCollisionsWithEntities() {
		List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.expand(2D, 2D, 2D));
		if (list != null && list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				Entity entity = (Entity) list.get(i);
				if (!(entity instanceof Vehicle)) {
					worldObj.sim.addPhysicsToEntity(entity);
				}
			}
	
		}
	}


	@Override
	public boolean canBePushed() {
		return false;
	}
	
	@Override
	public boolean canBeCollidedWith() {
		return false;
	}

	public AxisAlignedBB getCollisionBox(Entity entity) {
//		return entity.boundingBox; 
		return null;
	}

	public AxisAlignedBB getBoundingBox() {
//		return boundingBox;
		return null;
	}
	

	public Vector4f parentVelToLocal(Vector4f parentVel) {
		return VehicleUtil.parentVelToLocal(parentVel, getRotVector3f());
			
	}

	public Vector4f localVelToParent(Vector4f localVel) {
		return VehicleUtil.localVelToParent(localVel, getRotVector3f());
	}
	
    public List<AxisAlignedBB> getCollidingBoundingBoxes(Entity entity, AxisAlignedBB parentBB) {
    	AxisAlignedBB localBB = getLocalBoundingBox(parentBB);
    	List localBBs = vehicleBlocks.getCollidingBoundingBoxes(entity, localBB);
    	List<AxisAlignedBB> parentBBs = new ArrayList<AxisAlignedBB>();
    	for (int i=0; i<localBBs.size(); i++) {
    		AxisAlignedBB bb = (AxisAlignedBB) localBBs.get(i);
    		parentBBs.add(getParentBoundingBox(bb));
    	}
    	return parentBBs;
    }

	private AxisAlignedBB getLocalBoundingBox(AxisAlignedBB parentBB) {
		Vector4f localPos = parentPosToLocal(new Vector4f((float)(parentBB.maxX + parentBB.minX)/2F, (float)(parentBB.maxY + parentBB.minY)/2F, (float)(parentBB.maxZ + parentBB.minZ)/2F, 1F));
		Vector4f halfSize = new Vector4f((float)(parentBB.maxX - parentBB.minX)/2F, (float)(parentBB.maxY - parentBB.minY)/2F, (float)(parentBB.maxZ - parentBB.minZ)/2F, 1F);
		return AxisAlignedBB.getBoundingBox(localPos.x - halfSize.x, localPos.y - halfSize.y, localPos.z - halfSize.z, localPos.x + halfSize.x, localPos.y + halfSize.y, localPos.z + halfSize.z);
	}
	
	private AxisAlignedBB getParentBoundingBox(AxisAlignedBB localBB) {
		Vector4f parentPos = localPosToParent(new Vector4f((float)(localBB.maxX + localBB.minX)/2F, (float)(localBB.maxY + localBB.minY)/2F, (float)(localBB.maxZ + localBB.minZ)/2F, 1F));
		Vector4f halfSize = new Vector4f((float)(localBB.maxX - localBB.minX)/2F, (float)(localBB.maxY - localBB.minY)/2F, (float)(localBB.maxZ - localBB.minZ)/2F, 1F);
		return new VehicleBlockBoundingBox(this, parentPos.x - halfSize.x, parentPos.y - halfSize.y, parentPos.z - halfSize.z, parentPos.x + halfSize.x, parentPos.y + halfSize.y, parentPos.z + halfSize.z);	
	}

}
